/*
 * DettaglioAllineamentoDB.java
 *
 * Created on 13 marzo 2009, 17.53
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package it.azienda.managerworkstandard.view;

import it.azienda.framework.persistenza.DAOConnectionSingleton;
import it.azienda.framework.utilita.Utilita;
import it.azienda.framework.view.Dettaglio;
import it.azienda.managerworkstandard.modello.BeanFatturaAcquisto;
import it.azienda.managerworkstandard.modello.BeanProdottiDdt;
import it.azienda.managerworkstandard.modello.BeanProdottiFattura;
import it.azienda.managerworkstandard.modello.BeanProdottiResoCliente;
import it.azienda.managerworkstandard.modello.BeanProdottiResoFornitore;
import it.azienda.managerworkstandard.modello.BeanProdottoDett;
import it.azienda.managerworkstandard.modello.BeanScontrinoDett;
import it.azienda.managerworkstandard.modello.BeanStoricoProdotto;
import java.io.File;
import java.io.FileWriter;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.GregorianCalendar;
import javax.faces.application.FacesMessage;
import javax.faces.component.UIViewRoot;
import javax.faces.component.html.HtmlForm;
import javax.faces.context.FacesContext;
import org.hibernate.Session;



/**
 *
 * @author Michele
 */
public class DettaglioAllineamentoDB extends Dettaglio{
    
    /** Creates a new instance of DettaglioAllineamentoDB */
    public DettaglioAllineamentoDB() {}
    
    
    private File nuovoFile;
    private FileWriter fw;
    private String nomeFile= "allineamentoDb_";
    
    public void esegui(){
        String url2 = "/allineamentoDBMS.jsf";
        FacesContext ctx = FacesContext.getCurrentInstance();
        UIViewRoot view = ctx.getApplication().getViewHandler().createView(ctx,url2);
        view.setViewId(url2);
        ctx.setViewRoot(view);
        ctx.renderResponse();
    }
    
    public void calcola(){
        String esito = "";
        GregorianCalendar gregorian = new GregorianCalendar();
        gregorian.setTime(new java.util.Date(System.currentTimeMillis()));
        String anno = new Integer(gregorian.get(Calendar.YEAR)).toString();
        String mese = new Integer(gregorian.get(Calendar.MONTH) + 1).toString();
        String giorno = new Integer(gregorian.get(Calendar.DAY_OF_MONTH)).toString();
        String minuti = new Integer(gregorian.get(Calendar.MINUTE)).toString();
        
        String[] azzera = Utilita.getRequest().getParameterValues("azzera");
        try{
            String base = System.getenv("Utils_ManagerWork");
            this.nuovoFile = new File(base+"/"+nomeFile+anno+mese+giorno+minuti);
            this.fw = new FileWriter(this.nuovoFile);
            
            try{
                this.fw.write("*** INIZIO ALLINEAMENTO *** \r\n");
                this.fw.flush();
            }catch(Exception e){}
            
            //Step 1 --> Modifica agli id dei prodotti tramite il codice prodotto
            Session sessione = DAOConnectionSingleton.newSession();
            String queryM = "select prodotti from BeanProdottiFattura prodotti";
            
            ArrayList listaProdotti = (ArrayList)sessione.createQuery(queryM).list();
            for(int i=0; i<listaProdotti.size(); i++){
                BeanProdottiFattura prod = (BeanProdottiFattura)listaProdotti.get(i);
                queryM = "select id from BeanProdottoDett beanProdottoDett" +
                        " where codice = :codice";
                ArrayList listaId = (ArrayList)sessione.createQuery(queryM).setString("codice", prod.getCodiceProdDett()).list();
                
                if(listaId.size() > 0){
                    Integer id = (Integer)listaId.get(0);
                    if(prod.getProdottoId() == null){
                        prod.setProdottoId(id);
                        prod.modifica();
                    }else if(prod.getProdottoId().compareTo(id) != 0){
                        prod.setProdottoId(id);
                        prod.modifica();
                    }
                }
            }
            
            try{
                this.fw.write("PASSO 1: Allineamento ID fatture effettuato! \r\n");
                this.fw.flush();
            }catch(Exception e){}
            
            Runtime.getRuntime().gc();
            esito += " Allineamento ID fatture effettuato!";
            
            queryM = "select prodotti from BeanProdottiResoFornitore prodotti";
            listaProdotti = (ArrayList)sessione.createQuery(queryM).list();
            for(int i=0; i<listaProdotti.size(); i++){
                BeanProdottiResoFornitore prod = (BeanProdottiResoFornitore)listaProdotti.get(i);
                queryM = "select id from BeanProdottoDett beanProdottoDett" +
                        " where codice = :codice";
                
                ArrayList listaId = (ArrayList)sessione.createQuery(queryM).setString("codice", prod.getCodiceProdDett()).list();
                
                if(listaId.size() > 0){
                    Integer id = (Integer)listaId.get(0);
                    if(id != null){
                        if(prod.getProdottoId() == null){
                            prod.setProdottoId(id);
                            prod.modifica();
                        }else if(prod.getProdottoId().compareTo(id) != 0){
                            prod.setProdottoId(id);
                            prod.modifica();
                        }
                    }
                }
            }
            try{
                this.fw.write("PASSO 2: Allineamento ID resi fornitore effettuato! \r\n");
                this.fw.flush();
            }catch(Exception e){}
            
            
            queryM = "select prodotti from BeanProdottiResoCliente prodotti";
            listaProdotti = (ArrayList)sessione.createQuery(queryM).list();
            for(int i=0; i<listaProdotti.size(); i++){
                BeanProdottiResoCliente prod = (BeanProdottiResoCliente)listaProdotti.get(i);
                queryM = "select id from BeanProdottoDett beanProdottoDett" +
                        " where codice = :codice";
                
                ArrayList listaId = (ArrayList)sessione.createQuery(queryM).setString("codice", prod.getCodiceProdDett()).list();
                
                if(listaId.size() > 0){
                    Integer id = (Integer)listaId.get(0);
                    if(id != null){
                        if(prod.getProdottoId() == null){
                            prod.setProdottoId(id);
                            prod.modifica();
                        }else if(prod.getProdottoId().compareTo(id) != 0){
                            prod.setProdottoId(id);
                            prod.modifica();
                        }
                    }
                }
            }
            try{
                this.fw.write("PASSO 3: Allineamento ID resi cliente effettuato! \r\n");
                this.fw.flush();
            }catch(Exception e){}
            
            Runtime.getRuntime().gc();
            esito += " Allineamento ID resi effettuato!";
            
            queryM = "select prodotti from BeanProdottiDdt prodotti";
            listaProdotti = (ArrayList)sessione.createQuery(queryM).list();
            for(int i=0; i<listaProdotti.size(); i++){
                BeanProdottiDdt prod = (BeanProdottiDdt)listaProdotti.get(i);
                queryM = "select id from BeanProdottoDett beanProdottoDett" +
                        " where codice = :codice";
                ArrayList listaId = (ArrayList)sessione.createQuery(queryM).setString("codice", prod.getCodiceProdDett()).list();
                
                if(listaId.size() > 0){
                    Integer id = (Integer)listaId.get(0);
                    if(id != null){
                        if(prod.getProdottoId() == null){
                            prod.setProdottoId(id);
                            prod.modifica();
                        }else if(prod.getProdottoId().compareTo(id) != 0){
                            prod.setProdottoId(id);
                            prod.modifica();
                        }
                    }
                }
            }
            
            try{
                this.fw.write("PASSO 3: Allineamento ID Ddt effettuato! \r\n");
                this.fw.flush();
            }catch(Exception e){}
            Runtime.getRuntime().gc();
            esito += " Allineamento ID ddt effettuato!";
            
            try{
                String querUpDate = "update BeanScontrinoDett scontrinidett set scontrinidett.prodottoId = " +
                        " (select distinct(id) from BeanProdottoDett prodottidett " +
                        " where scontrinidett.codiceProdDett = prodottidett.codice)";
                DAOConnectionSingleton.beginTransaction();
                int esitoUpdate = sessione.createQuery(querUpDate).executeUpdate();
                DAOConnectionSingleton.commitTransaction();
            }catch(Exception ex2){
                this.fw.write("*** Errore passo 3 ! ***"+ex2.toString()+"\r\n");
                this.fw.flush();
            }
            /*
            queryM = "select scontriniDett from BeanScontrinoDett scontriniDett";
            listaProdotti = (ArrayList)sessione.createQuery(queryM).list();
            for(int i=0; i<listaProdotti.size(); i++){
                BeanScontrinoDett prod = (BeanScontrinoDett)listaProdotti.get(i);
                queryM = "select id from BeanProdottoDett beanProdottoDett" +
                        " where codice = :codice";
             
                ArrayList listaId = (ArrayList)sessione.createQuery(queryM).setString("codice", prod.getCodiceProdDett()).list();
             
                if(listaId.size() > 0){
                    Integer id = (Integer)listaId.get(0);
                    if(id != null){
                        if(prod.getProdottoId() == null){
                            prod.setProdottoId(id);
                            prod.modifica();
                        }else if(prod.getProdottoId().compareTo(id) != 0){
                            prod.setProdottoId(id);
                            prod.modifica();
                        }
                    }
                }
            }
             */
            
            try{
                this.fw.write("PASSO 4: Allineamento ID scontrini effettuato! \r\n");
                this.fw.flush();
            }catch(Exception e){}
            Runtime.getRuntime().gc();
            esito += " Allineamento ID scontrini effettuato!";
            
            //STEP 2
            // Per ogni prodotto calcolo la giacenza effettiva
            
            try{
                this.fw.write("PASSO 5: INIZIO CALCOLO GIACENZE EFFETTIVE \r\n");
                this.fw.flush();
            }catch(Exception e){}
            
            sessione = DAOConnectionSingleton.newSession();
            queryM = "select prodottidett.id" +
                    " from BeanProdottoDett prodottidett" +
                    " order by prodottidett.codice";
            listaProdotti = (ArrayList)sessione.createQuery(queryM).list();
            
            for(int i=0; i<listaProdotti.size(); i++){
                sessione = DAOConnectionSingleton.newSession();
                Integer id = (Integer)listaProdotti.get(i) ;
                
                if(id != null){
                    Double quantitaAcquistata =  new Double(0);
                    Double quantitaVend = new Double(0);
                    
                    queryM = "select sum(storicoprodotti.quantita),prodottidett.codice" +
                            " from BeanStoricoProdotto storicoprodotti, BeanProdottoDett prodottidett" +
                            " where storicoprodotti.beanProdottoDett.id = prodottidett.id" +
                            " and prodottidett.id = :id" +
                            " group by prodottidett.id,prodottidett.id,prodottidett.codice" +
                            " order by prodottidett.codice";
                    
                    Object[] objQuantita = (Object[])sessione.createQuery(queryM).setInteger("id", id.intValue()).uniqueResult();
                    if(objQuantita != null){
                        quantitaAcquistata = (Double)objQuantita[0];
                    }
                    
                    //Fatture
                    String query = "select sum(prodotti.quantitaProdDett) from BeanProdottiFattura prodotti" +
                            " where prodotti.prodottoId = :prodottoId";
                    Double qua = (Double)sessione.createQuery(query).setInteger("prodottoId",id.intValue()).uniqueResult();
                    
                    if(qua != null){
                        quantitaVend = new Double(quantitaVend.doubleValue() +  qua.doubleValue());
                    }
                    
                    //Scontrini
                    query = "select sum(prodotti.quantitaProdDett) from BeanScontrinoDett prodotti" +
                            " where prodotti.prodottoId = :prodottoId";
                    qua = (Double)sessione.createQuery(query).setInteger("prodottoId",id.intValue()).uniqueResult();
                    
                    if(qua != null){
                        quantitaVend = new Double(quantitaVend.doubleValue() +  qua.doubleValue());
                    }
                    
                    //ResoFornitore
                    query = "select sum(prodotti.quantitaProdDett) from BeanProdottiResoFornitore prodotti" +
                            " where prodotti.prodottoId = :prodottoId";
                    qua = (Double)sessione.createQuery(query).setInteger("prodottoId",id.intValue()).uniqueResult();
                    
                    if(qua != null){
                        quantitaVend = new Double(quantitaVend.doubleValue() +  qua.doubleValue());
                    }
                    
                    //ResoCliente
                    query = "select sum(prodotti.quantitaProdDett) from BeanProdottiResoCliente prodotti" +
                            " where prodotti.prodottoId = :prodottoId";
                    qua = (Double)sessione.createQuery(query).setInteger("prodottoId",id.intValue()).uniqueResult();
                    
                    if(qua != null){
                        quantitaVend = new Double(quantitaVend.doubleValue() -  qua.doubleValue());
                    }
                    
                    //Modifica
                    BeanProdottoDett prodottoDett = new BeanProdottoDett();
                    prodottoDett = (BeanProdottoDett)prodottoDett.dettaglio(id);
                    
                    Double scorta = new Double( quantitaAcquistata.doubleValue() - quantitaVend.doubleValue() );
                    
                    if(quantitaAcquistata.compareTo(quantitaVend) < 0){
                        String queryStorico = "select storicoprodotti.beanFatturaAcquisto " +
                                " from BeanStoricoProdotto storicoprodotti" +
                                " where storicoprodotti.beanProdottoDett.id = :id" +
                                " and storicoprodotti.beanFatturaAcquisto.data = (select min(a.beanFatturaAcquisto.data) " +
                                "                             from BeanStoricoProdotto a" +
                                "                             where a.beanProdottoDett.id = :id)";
                        sessione = DAOConnectionSingleton.newSession();
                        ArrayList listaFatture = (ArrayList)sessione.createQuery(queryStorico)
                        .setInteger("id", id.intValue())
                        .list();
                        
                        if(listaFatture.size() != 0){
                            BeanFatturaAcquisto beanFatturaAcquisto = (BeanFatturaAcquisto)listaFatture.get(0);
                            BeanStoricoProdotto beanStorico = new BeanStoricoProdotto();
                            beanStorico.setQuantita(new Double(scorta.doubleValue() * -1));
                            beanStorico.setBeanProdottoDett(prodottoDett);
                            beanStorico.setBeanFatturaAcquisto(beanFatturaAcquisto);
                            beanStorico.inserisci();
                        }else{
                            BeanFatturaAcquisto beanFatturaAcquisto = new BeanFatturaAcquisto();
                            beanFatturaAcquisto.setId(new Integer(629));
                            BeanStoricoProdotto beanStorico = new BeanStoricoProdotto();
                            beanStorico.setQuantita(new Double(scorta.doubleValue() * -1));
                            beanStorico.setBeanProdottoDett(prodottoDett);
                            beanStorico.setBeanFatturaAcquisto(beanFatturaAcquisto);
                            beanStorico.inserisci();
                        }
                    }
                    
                    if(prodottoDett.getScorta() == null){
                        prodottoDett.setScorta(new Double(0));
                    }
                    scorta = arrotonda(scorta,2);
                    
                    Double differenza = new Double(prodottoDett.getScorta().intValue() - scorta.intValue());
                    differenza = arrotonda(differenza,2);
                    
                    try{
                        this.fw.write("Prodotto--> ID "+valore(prodottoDett.getId().toString(), 6)+" - Codice: "+valore(prodottoDett.getCodice(), 15)+
                                " - Scorta prodotto: " +valore(prodottoDett.getScorta().toString(), 20)+" - Scorta calcolata: "+valore(scorta.toString(), 20)+
                                " - Differenza: "+valore(differenza.toString(), 20)+"\r\n");
                        this.fw.flush();
                    }catch(Exception e){}
                    
                    if(azzera != null && scorta.compareTo(new Double(0)) < 0){
                        prodottoDett.setScorta(new Double(0));
                    }else{
                        prodottoDett.setScorta(scorta);
                    }
                    prodottoDett.modifica();
                    
                }
                Runtime.getRuntime().gc();
            }
            
            try{
                this.fw.write("*** Allineamento DBMS completato! *** \r\n");
                this.fw.flush();
            }catch(Exception e){}
            esito += " Allineamento DBMS completato!";
            
        }catch(Exception e){
            esito += "ERRORE: "+e.toString();
            try{
                this.fw.write(esito);
                this.fw.close();
            }catch(Exception e2){}
        }
        
        FacesContext ctx = FacesContext.getCurrentInstance();
        HtmlForm form = (HtmlForm)ctx.getViewRoot().findComponent("erroriDataBase");
        form.setRendered(true);
        ctx.addMessage("erroriDataBase", new FacesMessage("erroriDataBase",esito));
        
        return;
    }
    
    public String valore(String valore, int pos){
        String campo = "";
        if(valore == null){
            for(int i=0; i<pos; i++){
                campo += " ";
            }
        }else{
            for(int i=valore.length(); i<pos; i++){
                campo += " ";
            }
        }
        valore =  valore.toString() + campo.toString();
        return valore;
    }
    
    public Double arrotonda(Object obj,int precisione){
        Double valore=(Double)obj;
        Double valoreArr=new Double(0);
        double pot = Math.pow(10, precisione);
        double  v = valore.doubleValue() * pot;
        valoreArr = new Double(Math.round(v) / pot);
        return valoreArr;
    }
}
